﻿// Copyright 2009 Mike Geise
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Falcon.Core.Extensions
{
	using System;
	using System.Globalization;
	using System.IO;
	using System.Text;
	using System.Web.Mvc;
	using System.Web.Routing;
	using System.Web.UI;
	using Falcon.Core.ActionResults.Enums;
	using Falcon.Core.ActionResults.ViewModels;
	using Falcon.Core.Collections;
	using Falcon.Core.Domain;
	using Falcon.Core.Helpers;
	using Falcon.Core.Menu;
	using Falcon.Core.Widgets;

	public static class HtmlExtension
	{
		/// <summary>
		/// Renders & displays the pager.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <typeparam name="TK"></typeparam>
		/// <param name="helper">The helper.</param>
		/// <param name="items">The items.</param>
		/// <param name="route">The route.</param>
		/// <returns>The pager</returns>
		public static string Pager<T, TK>(this HtmlHelper helper, IPagedList<T, TK> items, string route)
		{
			return new PagerHelper<T, TK>(helper.ViewContext.RequestContext, items, route).Render();
		}

		/// <summary>
		/// Renders & displays the menu.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="items">The items.</param>
		/// <returns>The menu</returns>
		public static string Menu(this HtmlHelper helper, Action<IMenuItemBuilder> items)
		{
			return new MenuHelper(helper.ViewContext.RequestContext, CreateMenuBuilder(items)).Render();
		}

		/// <summary>
		/// Displays the image.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="image">The image.</param>
		/// <param name="alt">The alt.</param>
		/// <returns></returns>
		public static string Image(this HtmlHelper helper, string image, string alt)
		{
			return Image(helper, image, alt, null);
		}

		/// <summary>
		/// Displays the image.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="image">The image.</param>
		/// <param name="alt">The alt.</param>
		/// <param name="attributes">The attributes.</param>
		/// <returns></returns>
		public static string Image(this HtmlHelper helper, string image, string alt, object attributes)
		{
			var builder = new TagBuilder("img");

			builder.MergeAttribute("src", string.Concat(Settings.ImagePath.AsRoot(), "/", image));
			builder.MergeAttribute("alt", alt);
			builder.MergeAttribute("title", alt);
			builder.MergeAttributes(new RouteValueDictionary(attributes));

			return builder.ToString(TagRenderMode.SelfClosing);
		}

		/// <summary>
		/// Displays the message.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <returns>The message</returns>
		/// note: refactor this to use the mvc tag helper
		public static string Message(this HtmlHelper helper)
		{
			var value = helper.ViewContext.TempData["message.result"];

			if (value != null)
			{
				var message = value.As<MessageViewModel>();
				var builder = new StringBuilder();

				using (var writer = new StringWriter(builder, CultureInfo.InvariantCulture))
				{
					using (var html = new XhtmlTextWriter(writer))
					{
						html.AddAttribute(HtmlTextWriterAttribute.Class, "message");
						html.RenderBeginTag(HtmlTextWriterTag.Div);

						switch (message.Scope)
						{
							case MessageScope.Error:
								html.AddAttribute(HtmlTextWriterAttribute.Class, "error");
								break;
							case MessageScope.Warning:
								html.AddAttribute(HtmlTextWriterAttribute.Class, "warning");
								break;
							default:
								html.AddAttribute(HtmlTextWriterAttribute.Class, "success");
								break;
						}

						html.RenderBeginTag(HtmlTextWriterTag.Div);

						html.RenderBeginTag(HtmlTextWriterTag.Ul);

						html.RenderBeginTag(HtmlTextWriterTag.Li);
						html.Write(message.Message);
						html.RenderEndTag();
						html.WriteLine();

						html.RenderEndTag();
						html.RenderEndTag();
						html.RenderEndTag();

						html.AddAttribute(HtmlTextWriterAttribute.Class, "clear");
						html.RenderBeginTag(HtmlTextWriterTag.Div);
						html.RenderEndTag();
					}
				}

				return builder.ToString();
			}

			return string.Empty;
		}

		/// <summary>
		/// Renders the specified widget.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="name">The name.</param>
		public static void Widget(this HtmlHelper helper, string name)
		{
			Widget(helper, name, null);
		}

		/// <summary>
		/// Renders the specified widget.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="name">The name.</param>
		/// <param name="attributes">The attributes.</param>
		public static void Widget(this HtmlHelper helper, string name, object attributes)
		{
			var widget = Application.Resolve<IWidget>(name);

			if (widget == null)
			{
				return;
			}

			widget.Attributes = new RouteValueDictionary(attributes);

			widget.Render(helper.ViewContext);
		}

		/// <summary>
		/// Displays the validation result.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <returns>The validation results</returns>
		/// note: refactor this to use the mvc tag helper
		public static string ValidationResult(this HtmlHelper helper)
		{
			if (helper.ViewData.ModelState.IsValid)
			{
				return string.Empty;
			}

			var builder = new StringBuilder();

			using (var writer = new StringWriter(builder, CultureInfo.InvariantCulture))
			{
				using (var html = new XhtmlTextWriter(writer))
				{
					html.AddAttribute(HtmlTextWriterAttribute.Class, "message");
					html.RenderBeginTag(HtmlTextWriterTag.Div);

					html.AddAttribute(HtmlTextWriterAttribute.Class, "error");
					html.RenderBeginTag(HtmlTextWriterTag.Div);

					html.RenderBeginTag(HtmlTextWriterTag.Ul);

					var i = 1;

					foreach (var pair in helper.ViewData.ModelState)
					{
						foreach (var error in pair.Value.Errors)
						{
							html.RenderBeginTag(HtmlTextWriterTag.Li);
							html.Write(string.Format(CultureInfo.InvariantCulture, "{0}. {1}", i, error.ErrorMessage));
							html.RenderEndTag();
							html.WriteLine();

							i++;
						}
					}

					html.RenderEndTag();
					html.RenderEndTag();
					html.RenderEndTag();

					html.AddAttribute(HtmlTextWriterAttribute.Class, "clear");
					html.RenderBeginTag(HtmlTextWriterTag.Div);
					html.RenderEndTag();
				}
			}

			return builder.ToString();
		}

		/// <summary>
		/// Creates the menu builder.
		/// </summary>
		/// <param name="items">The items.</param>
		/// <returns>The created menu item builder</returns>
		private static MenuItemBuilder CreateMenuBuilder(Action<IMenuItemBuilder> items)
		{
			var builder = new MenuItemBuilder();

			if (items != null)
			{
				items(builder);
			}

			return builder;
		}
	}
}